package com.hk.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hk.auth.StpKit;
import com.hk.common.Constant;
import com.hk.enums.UserRoleEnum;
import com.hk.exception.BusinessException;
import com.hk.exception.ErrorCode;
import com.hk.exception.ThrowExceptionUtil;
import com.hk.mapper.UserMapper;
import com.hk.model.entity.User;
import com.hk.model.vo.IdVO;
import com.hk.model.vo.user.*;
import com.hk.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 20231
 * @description 针对表【user(用户表)】的数据库操作Service实现
 * @createDate 2024-12-11 20:38:27
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Override
    public Long register(UserRegisterVO userRegisterVO) {
        String userAccount = userRegisterVO.getUserAccount();
        String password = userRegisterVO.getPassword();
        String checkPassword = userRegisterVO.getCheckPassword();
        ThrowExceptionUtil.throwIf(StrUtil.hasBlank(userAccount, password, checkPassword), ErrorCode.ERROR_PARAM, "参数为空");
        ThrowExceptionUtil.throwIf(!password.equals(checkPassword), ErrorCode.ERROR_PARAM, "两次输入的密码不一致");
        User exitsUser = this.selectByAccount(userAccount);
        ThrowExceptionUtil.throwIf(ObjectUtil.isNotNull(exitsUser), ErrorCode.ERROR_PARAM, "账号已存在");
        String md5 = DigestUtil.md5Hex(password);
        User user = new User();
        user.setUserAccount(userAccount);
        user.setPassword(md5);
        user.setRole(UserRoleEnum.USER.getCode());
        boolean save = this.save(user);
        if (!save) {
            throw new BusinessException(ErrorCode.ERROR_SYSTEM, "注册失败");
        }
        return user.getId();
    }

    @Override
    public UserVO login(UserLoginVO loginVO, HttpServletRequest request) {
        String userAccount = loginVO.getUserAccount();
        String password = loginVO.getPassword();
        User exitsUser = this.selectByAccount(userAccount);
        ThrowExceptionUtil.throwIf(ObjectUtil.isNull(exitsUser), ErrorCode.ERROR_SYSTEM, "用户不存在");
        String md5 = DigestUtil.md5Hex(password);
        ThrowExceptionUtil.throwIf(ObjectUtil.notEqual(md5, exitsUser.getPassword()), ErrorCode.ERROR_SYSTEM, "密码错误");
        UserVO userVO = converterUserVo(exitsUser);
        request.getSession().setAttribute(Constant.USER_LOGIN_STATE, userVO);
        StpKit.SPACE.login(userVO.getId());
        StpKit.SPACE.getSession().set(Constant.USER_LOGIN_STATE, userVO);
        return userVO;
    }

    @Override
    public UserVO getCurrentUser(HttpServletRequest request) {
        Object userObj = request.getSession().getAttribute(Constant.USER_LOGIN_STATE);
        ThrowExceptionUtil.throwIf(ObjectUtil.isNull(userObj), ErrorCode.NOT_LOGIN);
        UserVO userVO = (UserVO) userObj;
        User user = this.getById(userVO.getId());
        userVO = converterUserVo(user);
        return userVO;
    }

    @Override
    public void logout(HttpServletRequest request) {
        Object userObj = request.getSession().getAttribute(Constant.USER_LOGIN_STATE);
        ThrowExceptionUtil.throwIf(ObjectUtil.isNull(userObj), ErrorCode.NOT_LOGIN);
        request.getSession().removeAttribute(Constant.USER_LOGIN_STATE);
        StpKit.SPACE.logout();
    }

    @Override
    public UserVO addUser(UserEditVO userVO) {
        User user = this.selectByAccount(userVO.getUserAccount());
        ThrowExceptionUtil.throwIf(ObjectUtil.isNotNull(user), ErrorCode.ERROR_SYSTEM, "账号已存在");
        String password = userVO.getPassword();
        String checkPassword = userVO.getCheckPassword();
        ThrowExceptionUtil.throwIf(ObjectUtil.notEqual(password, checkPassword), ErrorCode.ERROR_PARAM, "两次输入密码不一致");
        user = new User();
        BeanUtil.copyProperties(userVO, user);
        user.setPassword(DigestUtil.md5Hex(password));
        boolean save = this.save(user);
        ThrowExceptionUtil.throwIf(!save, new BusinessException(ErrorCode.ERROR_SYSTEM, "添加失败"));
        return converterUserVo(user);
    }

    @Override
    public UserVO updateUser(UserEditVO userVO) {
        ThrowExceptionUtil.throwIf(ObjectUtil.isNull(userVO) || ObjectUtil.isNull(userVO.getId()), ErrorCode.ERROR_SYSTEM, "操作失败");
        User user = this.selectByAccount(userVO.getUserAccount());
        ThrowExceptionUtil.throwIf(ObjectUtil.isNotNull(user) && !user.getId().equals(userVO.getId()), ErrorCode.ERROR_SYSTEM, "账号已存在");
        user = new User();
        BeanUtil.copyProperties(userVO, user);
        boolean update = this.updateById(user);
        ThrowExceptionUtil.throwIf(!update, new BusinessException(ErrorCode.ERROR_SYSTEM, "修改失败"));
        return converterUserVo(user);
    }

    @Override
    public List<UserVO> getUserList(UserQueryParamVO queryParamVO) {
        String userName = queryParamVO.getUserName();
        Integer role = queryParamVO.getRole();
        String userAccount = queryParamVO.getUserAccount();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(userAccount), User::getUserAccount, userAccount);
        queryWrapper.like(StrUtil.isNotBlank(userName), User::getUserName, userName);
        queryWrapper.eq(ObjectUtil.isNotNull(role), User::getRole, role);
        return converterUserVo(this.list(queryWrapper));
    }

    @Override
    public List<UserVO> getUserListById(List<Long> userIdList) {
        return converterUserVo(this.listByIds(userIdList));
    }

    @Override
    public Page<UserVO> getUserPageList(UserQueryParamVO queryParamVO) {
        String userName = queryParamVO.getUserName();
        Integer role = queryParamVO.getRole();
        String userAccount = queryParamVO.getUserAccount();
        int current = queryParamVO.getCurrent();
        int pageSize = queryParamVO.getPageSize();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(userAccount), User::getUserAccount, userAccount);
        queryWrapper.like(StrUtil.isNotBlank(userName), User::getUserName, userName);
        queryWrapper.eq(ObjectUtil.isNotNull(role), User::getRole, role);
        IPage<User> userPage = this.page(new Page<>(current, pageSize), queryWrapper);
        List<User> records = userPage.getRecords();
        Page<UserVO> resultPage = new Page<>(current, pageSize, userPage.getTotal());
        resultPage.setRecords(converterUserVo(records));
        return resultPage;
    }

    @Override
    public UserVO getUserInfo(Long id) {
        User user = this.getById(id);
        return converterUserVo(user);
    }

    @Override
    public void delete(IdVO idVO) {
        this.removeById(idVO.getId());
    }

    @Override
    public boolean isAdmin(HttpServletRequest request) {
        UserVO userVO = getCurrentUser(request);
        return userVO != null && (ObjUtil.equals(UserRoleEnum.ADMIN.getCode(), userVO.getRole()));
    }

    /**
     * 获取脱敏用户信息
     *
     * @param user
     * @return
     */
    private UserVO converterUserVo(User user) {
        if (user == null) return null;
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(user, userVO);
        return userVO;
    }

    private List<UserVO> converterUserVo(List<User> userList) {
        if (CollectionUtil.isEmpty(userList)) {
            return new ArrayList<>();
        }
        return userList.stream().map(this::converterUserVo).collect(Collectors.toList());
    }

    private User selectByAccount(String userAccount) {
        LambdaQueryWrapper<User> query = new LambdaQueryWrapper<>();
        query.eq(User::getUserAccount, userAccount);
        return this.baseMapper.selectOne(query);
    }
}




